package com.zx.chatroom.listener;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.corundumstudio.socketio.annotation.OnEvent;
import com.corundumstudio.socketio.annotation.OnJsonObject;
import com.zx.chatroom.po.GroupChat;
import com.zx.chatroom.po.GroupMembers;
import com.zx.chatroom.server.SocketServer;
import com.zx.chatroom.service.GroupChatService;
import com.zx.chatroom.service.LoginService;
import com.zx.chatroom.util.CONST;
import com.zx.chatroom.util.LogUtil;
import com.zx.chatroom.vo.Chat;
import com.zx.chatroom.vo.UserVo;
import com.zx.framework.core.util.DateTimeUtil;
import com.zx.framework.core.util.FileUtil;
import com.zx.framework.core.util.SpringBeanUtil;
import com.zx.framework.core.util.StringUtil;

/**
 * 群组主类
 * @author shizhenhua
 *
 */
public class TalkListener extends BaseListener {

	private static final Logger LOGGER = Logger.getLogger(TalkListener.class);
	
	private static TalkListener instance;
	private TalkListener() {
		
	}
	public static TalkListener getInstance() {
		if (instance == null) {
			synchronized (TalkListener.class) {
				if (instance == null) {
					instance = new TalkListener();
				}
			}
		}
		return instance;
	}
	
	/**
	 * 所有用户信息
	 * put(userid,userVo);
	 */
	public static Map<String, UserVo> USER_LIST = new Hashtable<String, UserVo>();
	/**
	 * 保存用户SOCKET
	 * put(userId,SocketIOClient);
	 */
	private static Map<String, SocketIOClient> USER_SOCKET = new Hashtable<String, SocketIOClient>();
	/**
	 * sessionid和userid的关系,离开移除
	 * put(client.getSessionId(),userid);
	 */
	private static Map<String, String> SESSIONID_USER = new Hashtable<String, String>();
	/**
	 * 所有登陆到大厅的用户
	 * put(userid,userVo);离开移除
	 */
	private static Map<String, UserVo> ONLINE_USER = new Hashtable<String, UserVo>();
	/**
	 * 用户在线时间
	 * userid和data.getTime()
	 * pub(userid,times);
	 */
	private static Map<String, Long> USER_ONLINE_TIME = new Hashtable<String, Long>();
	
	@OnConnect
	public void onConnect(SocketIOClient client) {
		LOGGER.info(client.getSessionId()+"进入大厅！");
	}

	@OnDisconnect
	public void onDisconnect(SocketIOClient client) {
		LOGGER.info(client.getSessionId()+"离开大厅！");
		try{
			String userId = SESSIONID_USER.get(client.getSessionId().toString());
			if (StringUtil.isNotEmpty(userId)) {
				UserVo userVo = findOnlineUserByUserId(userId);
				if (null != userVo) {
					userLeave(userVo.getId(),client.getSessionId().toString());
				}
			}
		}catch(Exception e){
			e.printStackTrace();
			LOGGER.error(e);
		}
	}
	
	@OnEvent(value="connTalkRoom")
	public void connTalkRoom(String userId,SocketIOClient client){
		if (USER_SOCKET.containsKey(userId)) {
			SocketIOClient earlyClient =  findSocketByUserId(userId);
			earlyClient.sendEvent("leaveInfo", "您已在其它地方登录，被迫下线.");
			earlyClient.sendEvent("userLeaveClearPageInfo", earlyClient.getSessionId().toString());
			earlyClient.disconnect();
		}
		UserVo userVo = findLoginUserByUserId(userId);
		ONLINE_USER.put(userId, userVo);
		SESSIONID_USER.put(client.getSessionId().toString(), userId);
		USER_SOCKET.put(userId, client);
		// 设置在线
		userVo.setStatus(ONLINE);
		addGroupToList(client, userVo);
		if (userVo.getJobCode().equals(VISIT)) {//只记录营业员
			//记录用户在线时间
			USER_ONLINE_TIME.put(userId, new Date().getTime());
		}
	}
	/**
	 * 用户离开
	 * @param userId
	 */
	private void userLeave(String userId,String sessionId){
		UserVo leaveUserVo = findOnlineUserByUserId(userId);
		SocketIOClient leaveUserClient = findSocketByUserId(userId);
		if (null == leaveUserVo || null == leaveUserClient) {
			return ;
		}
		//更新列表
		removeUserToList(leaveUserVo.getId());
		SESSIONID_USER.remove(sessionId);
		ONLINE_USER.remove(leaveUserVo.getId());
		USER_SOCKET.remove(userId);
	}
	
	/**
	 * 页面增加聊天组列表
	 * @param client
	 * @param userId
	 * @param jobCode
	 */
	private void addGroupToList(SocketIOClient client,UserVo userVo) {
		userVo.setDate(DateTimeUtil.dateToString(new Date(), "yyyy-MM-dd HH:mm"));
		client.sendEvent("addGroupToList", gson.toJson(userVo));
	}
	
	/**
	 * 页面添加用户列表
	 * @param client
	 * @param newGroupId 新的群组ID
	 * @param oldGroupId 旧的裙组ID(上一个)
	 * @param userId
	 */
	@OnEvent("getGroupUserToList")
	private void getGroupUserToList(SocketIOClient client,String groupId,String userId) {
		UserVo userVo = findOnlineUserByUserId(userId);
		//设置进入群组状态
		if (null != userVo) {
			ONLINE_USER.get(userId).setStatus(BUSY);
		}
		//刷新该群组成员的用户列表
		List<UserVo> list = getUserByGroupid(groupId);
		SocketIOClient ather = null;
		for (UserVo user : list) {
			ather = USER_SOCKET.get(user.getId());
			ather.sendEvent("addUserToList", gson.toJson(list));
			ather.sendEvent("userCount", list.size());
			//发送离线信息
			if (!user.getId().equals(userId)) {
				//标识每个用户进入群组只显示一次的入群信息
				if (StringUtil.isEmpty(userVo.getTempMessage()) || userVo.getTempMessage().indexOf(","+groupId+",") == -1) {
					Chat chat = getChat(userVo,"进入群组!");
					chat.setGroupId(groupId);
					ONLINE_USER.get(userId).setTempMessage(userVo.getTempMessage()+","+groupId+",");
					ather.sendEvent("userMessage", gson.toJson(chat));
				}
			}
		}
		SocketIOClient userClient = findSocketByUserId(userId);
		//激活聊天窗口
		if (null != userClient) {
			GroupChatService groupChatService = SpringBeanUtil.getBean("groupChatService",GroupChatService.class);
			GroupChat groupChat = groupChatService.getGroupChatById(groupId);
			userClient.sendEvent("adapterWindows", gson.toJson(groupChat));
		}
	}
	
	/**
	 * 发送消息
	 * @param client
	 * @param groupMessage
	 * @param groupId 
	 * @param fromUserid 消息发送人
	 */
	@OnJsonObject
	public void sendMessage(SocketIOClient client ,Chat chat){
		if (null == chat) {
			return ;
		}
		talkLogCharInfo(chat);
		List<UserVo> list = getUserByGroupid(chat.getGroupId());
		SocketIOClient ather = null;
		for (UserVo user : list) {
			if (user.getStatus().equals(BUSY)) {
				ather = USER_SOCKET.get(user.getId());
				ather.sendEvent("receiveMessage", gson.toJson(chat));
			}
		}
	}
	
	/**
	 * 获取该群组所有用户
	 * @param groupid
	 * @return
	 */
	public List<UserVo> getUserByGroupid(String groupId){
		GroupChatService groupChatService = SpringBeanUtil.getBean("groupChatService",GroupChatService.class);
		List<UserVo> list = new ArrayList<UserVo>();
		List<GroupMembers> groupMemberss = groupChatService.getUserByGroupId(groupId);
		for (GroupMembers groupMembers : groupMemberss) {
			if (null == groupMembers) {
				continue;
			}
			UserVo userVo = findOnlineUserByUserId(groupMembers.getId().getUserid());
			//判断：用户只有进入该群组，该群组的其他用户的群组成员列表才能出现
			if (null != userVo && userVo.getStatus().equals(BUSY)) {
				list.add(userVo);
			}
		}
		return list;
	}
	/**
	 * 页面人员列表删除
	 * @param client
	 * @param userId
	 */
	private void removeUserToList(String userId) {
		GroupChatService groupChatService = SpringBeanUtil.getBean("groupChatService",GroupChatService.class);
		List<GroupMembers> groupMemberss = groupChatService.getGroupByUserId(userId);
		UserVo leaveUserVo = findOnlineUserByUserId(userId);
		for (GroupMembers groupMembers : groupMemberss) {
			List<UserVo> list = getUserByGroupid(groupMembers.getId().getGroupid());
			SocketIOClient ather = null;
			for (UserVo user : list) {
				if (user.getId().equals(userId)) {
					continue;
				}
				//删除离线用户
				ather = USER_SOCKET.get(user.getId());
				ather.sendEvent("removeUserToList", gson.toJson(leaveUserVo));
				//发送离线信息
				Chat chat = getChat(leaveUserVo,"离线!");
				chat.setGroupId(groupMembers.getId().getGroupid());
				ather.sendEvent("userMessage", gson.toJson(chat));
			}
		}
	}
	
	private Chat getChat(UserVo user,String message){
		Chat chat = new Chat();
		String jobstr = "";
		if (user.getJobCode().equals(CONST.SEAT)) {
			jobstr = "座席";
		} else if (user.getJobCode().equals(CONST.VISIT)) {
			jobstr = "营业员";
		}
		chat.setMessage(jobstr+"("+user.getUsername()+")"+message);
		return chat;
	}
	
	/**
	 * 异步加载自动回复信息
	 * @param client
	 */
	@OnEvent(value="autoReply")
	public void autoReply(SocketIOClient client){
		LoginService loginService = SpringBeanUtil.getBean("loginService",LoginService.class);
		client.sendEvent("autoReply", gson.toJson(loginService.getAllAutoReply()));
	}
	
	/**
	 * 保存聊天记录
	 * @param client
	 * @param msg
	 */
	@OnEvent(value="talkLogCharInfo")
	public void talkLogCharInfo(final Chat chat){
		LogUtil.talKLogChatInfo(SocketServer.getCharInfoOutPath(), chat);
	}
	
	/**
	 * 显示历史记录
	 * @param client
	 * @param _visitId
	 * @param _seatId
	 * @param dateStr
	 */
	@OnEvent(value = "talkHistoryInfoShow")
	public void historyInfoShow(SocketIOClient client,String _groupid,String dateStr){
		try {
			String path = SocketServer.getCharInfoOutPath()+dateStr+"/"+dateStr+"("+_groupid+").txt";
			File f = new File(path);
			if(f.isFile()){
				String info = FileUtil.readFileToString(f,"utf-8");
				client.sendEvent("hisInfo", info);
			}else{
				client.sendEvent("hisInfo", "暂无记录");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
	/**
	 * 获取用户Socket
	 * @param userId
	 * @return
	 */
	public static SocketIOClient findSocketByUserId(String userId){
		if (USER_SOCKET.containsKey(userId)) {
			return USER_SOCKET.get(userId);
		}
		return null;
	}
	
	/**
	 * 获得登陆用户信息
	 * @param userId
	 * @return
	 */
	private UserVo findLoginUserByUserId(String userId){
		if (USER_LIST.containsKey(userId)) {
			return USER_LIST.get(userId);
		}
		return null;
	}
	/**
	 * 获得在线用户信息
	 * @param userId
	 * @return
	 */
	public static UserVo findOnlineUserByUserId(String userId){
		if (ONLINE_USER.containsKey(userId)) {
			return ONLINE_USER.get(userId);
		}
		return null;
	}
}
